﻿using CommunicationLib;
using CommunicationLib.Model;
using PlcLib.Enums;
using PlcLib.Interface;
using PlcLib.Model;
using PlcLib.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PlcLib.Base
{
    public abstract class PlcBase : ObservableObject, IPlc
    {
        public abstract event Action<object, PlcEventArgs> OnMessage;//PLC消息事件
        public abstract event Action<object, PlcEventArgs> OnError;//PLC错误事件
        public abstract event Action<object, DataPackage> OnSend;//PLC发送数据事件
        public abstract event Action<object, DataPackage> OnReceived;//PLC
                                                                     //数据事件

        protected Communication communication = new Communication();//与下位机的通讯类
        protected AutoResetEvent sendWaiter = new AutoResetEvent(false);//自动重置事件，用于线程同步
        protected Queue<DataPackage> sendPackages = new Queue<DataPackage>();//下发指令队列
        protected readonly object sendLocker = new object();//发送锁，确保线程安全
        protected CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();//取消令牌源，用于异步操作的取消
        protected List<DataPackage> receivePackages = new List<DataPackage>();//接收指令集合
        protected readonly object receiveLocker = new object();//接收锁，确保线程安全
        protected long commandId = 1;//指令编号
        public abstract void Initialize(Net net);
        public abstract void Initialize(Port port);
        public abstract IPlcResult Read(Command command);
        public abstract Task<IPlcResult> ReadAsync(Command command);
        public abstract IPlcResult Send(byte[] array);
        public abstract Task<IPlcResult> SendAsync(byte[] array);
        public abstract IPlcResult Start(Action action);

        public abstract IPlcResult Write(Command command,int data);
        public abstract Task<IPlcResult> WriteAsync(Command command,int data);
        public abstract IPlcResult Write(Command command, List<int> data);
        public abstract Task<IPlcResult> WriteAsync(Command command, List<int> data);


        public abstract IPlcResult<T> Read<T>(Command command);
        public abstract IPlcResult<T> Write<T>(Command command, T data);
        public abstract Task<IPlcResult<T>> ReadAsync<T>(Command command);
        public abstract Task<IPlcResult<T>> WriteAsync<T>(Command command, T data);




        public virtual void Stop()//虚方法，可以被子类重写
        {
            communication.Stop();
            cancellationTokenSource.Cancel();
        }

        protected long GetCommandId()//获取指令编号
        {
            return Interlocked.Increment(ref commandId);
        }

        //属性成员
        private ConnectedState ConnectedState;//PLC连接状态
        /// <summary>
        /// 通讯状态
        /// </summary>
        public ConnectedState connectedState
        {
            get { return ConnectedState; }
            protected set { ConnectedState = value; RaisePropertyChanged(); }
        }

    }
}
